package com.example.movie.ui.movie.fragment

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.bumptech.glide.Glide
import com.example.movie.R
import com.example.movie.common.constants.AppConstants
import com.example.movie.common.constants.RequestCode
import com.example.movie.common.dsl.afterTextChanged
import com.example.movie.common.view.commentView.callback.CustomCommentItemCallback
import com.example.movie.common.view.commentView.callback.OnCommentLoadMoreCallback
import com.example.movie.common.view.commentView.callback.OnItemClickCallback
import com.example.movie.common.view.commentView.callback.OnReplyLoadMoreCallback
import com.example.movie.common.view.commentView.defaults.DefaultCommentHolder
import com.example.movie.common.view.commentView.defaults.DefaultCommentModel
import com.example.movie.common.view.commentView.defaults.DefaultReplyHolder
import com.example.movie.common.view.commentView.defaults.DefaultViewStyleConfigurator
import com.example.movie.common.view.commentView.utils.ViewUtil
import com.example.movie.common.view.commentView.view.ViewHolder
import com.example.movie.data.movie.factory.CommentViewModelFactory
import com.example.movie.data.movie.factory.MovieDetailViewModelFactory
import com.example.movie.data.movie.model.CommentViewModel
import com.example.movie.data.movie.model.MovieDetailViewModel
import com.example.movie.data.movie.model.MyComment
import com.example.movie.data.movie.model.MyReply
import com.example.movie.data.user.login.model.LoggedInUserView
import com.example.movie.data.user.login.model.SharedLoginViewModel
import com.example.movie.ui.user.auth.LoginActivity
import com.example.movie.utils.ContextHolder
import com.example.movie.utils.DateUtil
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog
import kotlinx.android.synthetic.main.fragment_comment.*
import kotlinx.android.synthetic.main.item_constellation.*
import kotlinx.android.synthetic.main.layout_reply.view.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.properties.Delegates


class CommentFragment : Fragment() {

    private val loginViewModel: SharedLoginViewModel = ContextHolder.getMainContext().loginViewModel
    private val movieDetailViewModel: MovieDetailViewModel by activityViewModels(factoryProducer = { MovieDetailViewModelFactory() })
    private val commentViewModel: CommentViewModel by activityViewModels(factoryProducer = { CommentViewModelFactory() })

    /**
     * 评论相关状态
     */
    private var hasInitCommentData = false
    private val defaultPageSize = 10
    private var currentPage = 1
    private var isRefreshing = false
    private var onClickGroupPos by Delegates.notNull<Int>()
    private var onClickChildPos by Delegates.notNull<Int>()

    /**
     * key应该使用id来标识，而不是位置，避免极端情况下发生错误
     */
    private val commentHolderMap = mutableMapOf<Int, ViewHolder>()

    /**
     * 回复相关状态
     */
    private val defaultReplyPageSize = 5
    private var isChildReply = false
    private  var toName:String? = null
    private var toId: String? = null

    /**
     * 选择的顶级评论id,标识动作是评论还是回复
     */
    private var pid = 0

    /**
     * 临时存储的恢复实体，当服务器确认恢复成功随即将恢复添加在ui中
     */
    private lateinit var tempReply: MyReply
    private lateinit var tempComment: MyComment

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        setObserver()
        return inflater.inflate(R.layout.fragment_comment, container, false)
    }

    private fun setObserver() {
        movieDetailViewModel.movieDetailData.observe(requireActivity(), { it ->
            it.success?.movieVo?.let {
                it.apply {
                    commentViewModel.loadForumPage(movieId!!, currentPage, defaultPageSize)
                }
            }
        })

        commentViewModel.addReplyState.observe(viewLifecycleOwner, {
            tempReply.id = it.toLong()
            val parent = commentView.commentList[onClickGroupPos] as MyComment
            if (parent.getReplies() == null) {
                parent.setReplies(mutableListOf())
            }
            //todo 添加回复之后要重新设置分页属性
            commentView.addReply(tempReply, onClickGroupPos)

            input.hint = " 说点什么吧"
            refreshInput("回复成功")
        })

        commentViewModel.addCommentState.observe(viewLifecycleOwner, {
            tempComment.id = it.toLong()
            commentView.addComment(tempComment)
            refreshInput("评论成功")
        })

        commentViewModel.approveState.observe(viewLifecycleOwner, {
            val commentHolder = commentHolderMap[it.forumId]!!
            if (it.hasApprove) {
                if (commentHolder is DefaultCommentHolder){
                    (commentView.commentList[onClickGroupPos] as MyComment).isLike = true
                    (commentView.commentList[onClickGroupPos] as MyComment).prizes++
                }else{
                    (commentView.commentList[onClickGroupPos].getReplies<MyReply>()[onClickChildPos] as MyReply).isLike = true
                    (commentView.commentList[onClickGroupPos].getReplies<MyReply>()[onClickChildPos] as MyReply).prizes++
                }

                commentHolder.prizes.text =
                    commentHolder.prizes.text.toString().toInt().inc().toString()
                commentHolder.prize.setImageResource(R.drawable.comment_approve)
            } else {
                if (commentHolder is DefaultCommentHolder){
                    (commentView.commentList[onClickGroupPos] as MyComment).isLike = false
                    (commentView.commentList[onClickGroupPos] as MyComment).prizes--
                }else{
                    (commentView.commentList[onClickGroupPos].getReplies<MyReply>()[onClickChildPos] as MyReply).isLike = false
                    (commentView.commentList[onClickGroupPos].getReplies<MyReply>()[onClickChildPos] as MyReply).prizes--
                }

                commentHolder.prizes.text =
                    commentHolder.prizes.text.toString().toInt().dec().toString()
                commentHolder.prize.setImageResource(R.drawable.pxjh)
            }
        })


        commentViewModel.commentList.observe(viewLifecycleOwner, { it ->
            it.success?.let {
                val commentModel = DefaultCommentModel()
                val comments = mutableListOf<DefaultCommentModel.Comment>()
                it.data?.let { data ->
                    repeat(data.size) { idx ->
                        val comment = MyComment()
                        data[idx].apply {
                            comment.id = forumId.toLong()
                            comment.headImg = headImg
                            comment.posterName = userName
                            comment.comment = remark
                            comment.prizes = countNumber.toInt()
                            comment.isLike = hasApprove
                            comment.date = DateUtil.parseDate(forumDate!!, "yyyy-MM-dd hh:mm:ss")

                            //初始化回复的总数据量和分页数目
                            comment.totalPages =
                                ((replySize + defaultReplyPageSize - 1) / defaultReplyPageSize)
                            //一开始不展示，点击展开更多回复才加载回复
                            comment.totalDataSize = replySize
                            comment.currentPage = 0
                            comment.nextPage = comment.currentPage + 1
                        }
                        comments.add(comment)
                    }
                }

                commentModel.totalPages =
                    ((it.recordsTotal!! + defaultPageSize - 1) / defaultPageSize).toInt()
                commentModel.currentPage = currentPage
                commentModel.nextPage = currentPage + 1
                commentModel.comments = comments

                when {
                    hasInitCommentData -> {
                        commentView.loadMoreComplete(commentModel)
                    }
                    isRefreshing -> {
                        commentView.refreshComplete(commentModel)
                        isRefreshing = false
                        initCommentsSuccess()
                    }
                    else -> {
                        commentView.loadComplete(commentModel)
                        initCommentsSuccess()
                    }
                }
            }
        })

        commentViewModel.replyList.observe(viewLifecycleOwner, { it ->
            it.success?.let { it ->
                val replyModel = DefaultCommentModel()
                val replies = mutableListOf<MyReply>()
                it.data?.let {
                    for (forumVo in it) {
                        val reply = MyReply()
                        forumVo.apply {
                            reply.headImg = headImg
                            reply.date = DateUtil.parseDate(forumDate!!, "yyyy-MM-dd hh:mm:ss")
                            reply.id = forumId.toLong()
                            reply.phoneNumber = fromId
                            reply.prizes = countNumber.toInt()
                            reply.reply = remark
                            reply.replierName = userName
                            reply.isLike = hasApprove
                            reply.pid = pid.toLong()
                            reply.toName = toName
                            reply.toId = toId
                        }
                        replies.add(reply)
                    }
                }
                val tmp = mutableListOf(MyComment())

                // todo 输入分页和数据量等信息
                tmp[0].replies = replies as List<DefaultCommentModel.Comment.Reply>?
                replyModel.comments = tmp as List<DefaultCommentModel.Comment>?

                commentView.loadMoreReplyComplete(replyModel);
            }
        })

    }

    private fun refreshInput(tip: String) {
        input.setText("")
        val successTipDialog = QMUITipDialog.Builder(requireContext())
            .setIconType(QMUITipDialog.Builder.ICON_TYPE_SUCCESS)
            .setTipWord(tip)
            .create()
        successTipDialog.show()
        Handler(Looper.myLooper()!!).postDelayed({
            successTipDialog.dismiss()
        }, TimeUnit.SECONDS.toMillis(1))
    }

    private fun initCommentsSuccess() {
        hasInitCommentData = true
    }

    /**
     * 刷新状态
     */
    private fun refreshSelectState() {
        pid = 0
        toName = null
        toId = null
        isChildReply = false
    }

    private fun getMovieId(): Int {
        return movieDetailViewModel.movieDetailData.value?.success?.movieVo?.movieId!!
    }

    private fun getCurrentUser(): LoggedInUserView {
        return loginViewModel.loginResult.value?.success!!
    }

    @SuppressLint("SetTextI18n")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        //设置空数据视图
        val emptyCommentLayout =
            LayoutInflater.from(context).inflate(R.layout.layout_comment_empty, null, false)
        commentView.setEmptyView(emptyCommentLayout)
        commentView.setViewStyleConfigurator(CustomStyleConfig(context))

        commentView
            .from(requireContext())
            .callbackBuilder()
            .setOnScrollCallback(null)
            .setOnCommentLoadMoreCallback(object : OnCommentLoadMoreCallback {
                override fun loading(
                    currentPage: Int,
                    willLoadPage: Int,
                    isLoadedAllPages: Boolean
                ) {
                    if (isLoadedAllPages) {
                        return
                    }
                    commentViewModel.loadForumPage(
                        getMovieId(),
                        willLoadPage,
                        defaultPageSize
                    )
                    this@CommentFragment.currentPage = willLoadPage
                }

                override fun complete() {
                }

                override fun failure(msg: String?) {
                }

            })
            .setOnReplyLoadMoreCallback(object : OnReplyLoadMoreCallback<MyReply> {

                override fun loading(reply: MyReply?, willLoadPage: Int) {
                    Log.i("reply", "$reply  willLoadPage: $willLoadPage")
                    commentViewModel.loadReplies(
                        reply!!.getPid(),
                        willLoadPage,
                        defaultReplyPageSize
                    )
                }

                override fun complete() {
                }

                override fun failure(msg: String?) {
                }

            })
            .setOnItemClickCallback(object :
                OnItemClickCallback<MyComment, DefaultCommentModel.Comment.Reply> {

                override fun commentItemOnClick(
                    position: Int,
                    comment: MyComment?,
                    view: View?
                ) {
                    if (!loginViewModel.isLoggedIn()) {
                        startActivityForResult(
                            Intent(context, LoginActivity::class.java),
                            RequestCode.NEED_LOGIN
                        )
                        return
                    }
                    onClickGroupPos = position
                    input.hint = "回复@${comment?.posterName}"
                    requestInput()
                    pid = comment!!.id.toInt()
                }

                override fun replyItemOnClick(
                    c_position: Int,
                    r_position: Int,
                    reply: DefaultCommentModel.Comment.Reply?,
                    view: View?
                ) {
                    val r = reply as MyReply
                    onClickGroupPos = c_position
                    input.hint = "回复@${r.replierName}"
                    requestInput()
                    isChildReply = true
                    toName = r.replierName
                    toId = r.phoneNumber
                    pid = reply.pid.toInt()
                }

            })
            .customCommentItem(CustomCommentItemCallback<MyComment> { groupPosition, comment, inflater, convertView, parent ->
                val myCommentHolder: DefaultCommentHolder
                var view: View? = convertView
                if (view == null) {
                    view = inflater.inflate(R.layout.item_comment, parent, false)
                    myCommentHolder = DefaultCommentHolder(view)
                    view.tag = myCommentHolder
                } else {
                    myCommentHolder = view.tag as DefaultCommentHolder
                }

                val tmp = comment as MyComment
                commentHolderMap[comment.id.toInt()] = myCommentHolder

                myCommentHolder.posterName.text = tmp.posterName
                myCommentHolder.content.text = tmp.comment
                myCommentHolder.time.text = ViewUtil.getTime(tmp.date)
                Glide
                    .with(requireContext())
                    .load(AppConstants.STATIC_SOURCE_URL + tmp.headImg)
                    .placeholder(R.mipmap.logo)
                    .error(R.drawable.error)
                    .into(myCommentHolder.ico)
                myCommentHolder.prizes.text = tmp.prizes.toString()

                myCommentHolder.prize.setOnClickListener {
                    onClickGroupPos = groupPosition
                    commentViewModel.approve(tmp.id.toInt())
                }

                //该用户已点赞该条评论
                if (tmp.isLike) {
                    myCommentHolder.prize.setImageResource(R.drawable.comment_approve)
                } else {
                    myCommentHolder.prize.setImageResource(R.drawable.pxjh)
                }

                return@CustomCommentItemCallback view

            })
            .customReplyItem { groupPosition, childPosition, isLastReply, reply, inflater, convertView, parent ->
                val myReplyHolder: DefaultReplyHolder
                var view: View? = convertView
                if (view == null) {
                    //covertView用于view的复用，如果为空才重新创建视图
                    view = inflater.inflate(R.layout.item_reply, parent, false)
                    myReplyHolder = DefaultReplyHolder(view)
                    view!!.tag = myReplyHolder
                } else {
                    myReplyHolder = view!!.tag as DefaultReplyHolder
                }
                val tmp = reply as MyReply
                commentHolderMap[reply.id.toInt()] = myReplyHolder

                if (tmp.toName != null){
                    myReplyHolder.replierName.text = "${tmp.replierName} ▶ ${tmp.toName}"
                }else{
                    myReplyHolder.replierName.text = tmp.replierName
                }
                myReplyHolder.content.text = tmp.reply
                myReplyHolder.time.text = ViewUtil.getTime(tmp.getDate())
                Glide
                    .with(requireContext())
                    .load(AppConstants.STATIC_SOURCE_URL + tmp.headImg)
                    .placeholder(R.mipmap.logo)
                    .error(R.drawable.error)
                    .into(myReplyHolder.ico)
                myReplyHolder.prizes.text = tmp.prizes.toString()
                myReplyHolder.prize.setOnClickListener {
                    onClickGroupPos = groupPosition
                    onClickChildPos = childPosition
                    commentViewModel.approve(tmp.id.toInt())
                }
                if (tmp.isLike) {
                    myReplyHolder.prize.setImageResource(R.drawable.comment_approve)
                } else {
                    myReplyHolder.prize.setImageResource(R.drawable.pxjh)
                }

                return@customReplyItem view

            }
            .buildCallback()

        input.afterTextChanged {
            send_btn.isEnabled = it.isNotBlank()
        }

        send_btn.setOnClickListener {
            sendMessage()
        }

    }

    private fun sendMessage() {
        val content = input.text.toString()
        val user = getCurrentUser()
        if (pid == 0) {
            //构建临时评论实体
            tempComment = MyComment()
            tempComment.headImg = user.headImg
            tempComment.posterName = user.nickName
            tempComment.date = Date().time
            tempComment.comment = content
            tempComment.prizes = 0
        } else {
            tempReply = MyReply()
            tempReply.reply = content
            tempReply.headImg = user.headImg
            tempReply.toName = toName
            tempReply.toId = toId
            tempReply.replierName = user.nickName
            tempReply.phoneNumber = user.phoneNumber
            tempReply.date = Date().time
            tempReply.prizes = 0
            tempReply.pid = pid.toLong()
        }
        commentViewModel.addForum(getMovieId(), content, pid, toId)
        refreshSelectState()
    }

    /**
     * 请求键盘输入
     */
    private fun requestInput() {
        input.requestFocus()
        val inputMethodService =
            requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputMethodService.showSoftInput(input, InputMethodManager.SHOW_IMPLICIT)
    }


    /**
     * 自定义评论配置
     */
     class CustomStyleConfig(context: Context?) : DefaultViewStyleConfigurator(context) {

        init {
            lm_footer_text = "这回真没了哥~"
        }

    }


}